﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using PostSharp.Aspects;

namespace GrayParrot.Infrastructure
{
    [Serializable]
    public class WithTrace : OnMethodBoundaryAspect
    {
        Type m_currentType = null;

        public WithTrace()
        {
        }

        public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo)
        {
            base.CompileTimeInitialize(method, aspectInfo);

            m_currentType = method.DeclaringType;
        }

        // Invoked only once at runtime from the static constructor of type declaring the target method.
        public override void RuntimeInitialize(MethodBase method)
        {
            string methodName = method.DeclaringType.FullName + method.Name;
        }

        public override void OnEntry(MethodExecutionArgs args)
        {
            Thread.BeginThreadAffinity();

            args.MethodExecutionTag = Stopwatch.StartNew();
        }

        public override void OnExit(MethodExecutionArgs args)
        {
            var sw = (Stopwatch)args.MethodExecutionTag;
            sw.Stop();

            Thread.EndThreadAffinity();

            GrayParrot.Logging.Logger.For(m_currentType).InfoFormat("Exit {0} (with exception); [{1} - {2}ms]", args.Method.Name, sw.Elapsed, sw.ElapsedMilliseconds);
        }

        public override void OnSuccess(MethodExecutionArgs args)
        {
            var sw = (Stopwatch)args.MethodExecutionTag;
            sw.Stop();

            Thread.EndThreadAffinity();

            GrayParrot.Logging.Logger.For(m_currentType).InfoFormat("Success {0}; ; [{1} - {2}ms]", args.Method.Name, sw.Elapsed, sw.ElapsedMilliseconds);
        }
    }
}
